package com.linkoog.devtools.websocket.toolwindow.right;


import com.intellij.icons.AllIcons;
import com.intellij.openapi.editor.event.DocumentAdapter;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.event.DocumentListener;
import com.intellij.refactoring.ui.StringTableCellEditor;
import com.intellij.ui.BooleanTableCellEditor;
import com.intellij.ui.JBColor;
import com.intellij.ui.TableUtil;
import com.intellij.ui.table.TableView;
import com.intellij.util.SmartList;
import com.intellij.util.ui.ColumnInfo;
import com.intellij.util.ui.ListTableModel;
import com.linkoog.devtools.intellij.ui.table.cell_editor.VoidRowCellEditer;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;



public class WebsocketHeaderTable extends TableView<WebsocketHeaderTable.ItemInfo> {


    public WebsocketHeaderTable() {
        setModelAndUpdateColumns(new ListTableModel<>(createColumnInfos(this), new SmartList(new ItemInfo())));
        //setBackground(Gray._248);
        getColumnModel().getColumn(0).setResizable(false);
        TableUtil.setupCheckboxColumn(getColumnModel().getColumn(0));
        getTableHeader().setReorderingAllowed(false);//禁止拖动表头
        setRowSelectionAllowed(false);
        //setBorder(Borders.empty(1));

        setForeground(JBColor.black);
        setBackground(JBColor.white);
        setSelectionForeground(JBColor.black);
        setSelectionBackground(JBColor.white);

        setRowMargin(1);
        setRowHeight(20);
        //setAutoResizeMode(AUTO_RESIZE_LAST_COLUMN);
        setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);

        setFocusable(false);
        setRequestFocusEnabled(false);

        addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                handleMouse(e);
            }

            @Override
            public void mouseReleased(MouseEvent e) {
                handleMouse(e);
            }

            private void handleMouse(MouseEvent e) {
                if (e.isPopupTrigger()) {
                    JPopupMenu menu = createPopup();
                    menu.show(e.getComponent(), e.getX(), e.getY());
                }
            }

            @Override
            public void mouseClicked(MouseEvent e) {
                int rowI = rowAtPoint(e.getPoint());// 得到table的行号
                int columnI = columnAtPoint(e.getPoint());// 得到table的列号

                if (rowI > -1 && columnI > -1) {
                    Object cellValue = (getModel()).getValueAt(rowI, columnI);
                    //System.out.println("单击鼠标 "+( rowI +1 )+"行"+ columnI +"列" + cellValue);
                    //System.out.println("getRowCount" + getRowCount());
                    if ("_$$delete$$_".equals(cellValue) && rowI != getRowCount() - 1) {
                        getListTableModel().removeRow(rowI);
                        getListTableModel().fireTableDataChanged();
                    }

                }
            }
        });
    }

    public void setFixColumnWidth(JTable table) {
        //this.setRowHeight(30);
        this.setAutoResizeMode(table.AUTO_RESIZE_OFF);

        //The following code can be used to fix table column width
        TableColumnModel tcm = table.getTableHeader().getColumnModel();
        for (int i = 0; i < tcm.getColumnCount(); i++) {
            TableColumn tc = tcm.getColumn(i);
            tc.setPreferredWidth(50);
            // tc.setMinWidth(100);
            tc.setMaxWidth(50);
        }
    }


    public void reloadData(List<ItemInfo> data) {
        SmartList<ItemInfo> list = new SmartList<>();
        if (data != null && !data.isEmpty()) {
            list.addAll(data);
        }

        //添加空白的最后一行
        list.add(new ItemInfo());

        getListTableModel().setItems(list);
        getListTableModel().fireTableDataChanged();
    }


    private JPopupMenu createPopup() {
        JPopupMenu popupMenu = new JPopupMenu();

//        TerminalAction.addToMenu(popupMenu, this);

        JMenuItem deleteLine = new JMenuItem("Delete", AllIcons.Actions.Cancel);

        deleteLine.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                System.out.println("actionEvent = [" + actionEvent + "]");
                if (getRowCount() > 1) {
                    getListTableModel().removeRow(getSelectedRow());
                }
            }
        });

        popupMenu.add(deleteLine);
        return popupMenu;
    }

    public Map<String, String> getKeyValue() {
        List<ItemInfo> items = getListTableModel().getItems();
        Map<String, String> result = new LinkedHashMap<>();
        items.stream().filter(item -> item.checkable && item.checked).forEach(item -> result.put(item.key, item.value));
        return result;
    }

    private static ColumnInfo[] createColumnInfos(WebsocketHeaderTable table) {
        ColumnInfo[] columnInfos = {
                new ColumnInfo<ItemInfo, Boolean>(" ") {
                    @Override
                    public int getWidth(JTable table) {
                        return 11;
                    }

                    @Override
                    public Class getColumnClass() {
                        return Boolean.class;
                    }

                    @Override
                    public Boolean valueOf(ItemInfo o) {
                        return o.checked;
                    }

                    @Override
                    public boolean isCellEditable(ItemInfo itemInfo) {
                        return itemInfo.checkable;
                    }

                    @Override
                    public void setValue(ItemInfo itemInfo, final Boolean value) {
                        itemInfo.checked = value;
                    }

                    @Nullable
                    @Override
                    public TableCellEditor getEditor(ItemInfo itemInfo) {
                        return new BooleanTableCellEditor();
                    }

                },
                new ColumnInfo<ItemInfo, String>("Name") {
                    /*@Override
                    public int getWidth(JTable jtable) {
                        return 222;
                    }*/

                    @Nullable
                    @Override
                    public String valueOf(ItemInfo itemInfo) {
                        return itemInfo.key;
                    }

                    @Override
                    public boolean isCellEditable(ItemInfo itemInfo) {
                        return itemInfo.isKeyEditable();
                    }

                    @Override
                    public void setValue(ItemInfo itemInfo, String value) {
                        itemInfo.key = value;
                    }

                    @Nullable
                    @Override
                    public TableCellEditor getEditor(ItemInfo itemInfo) {
                        StringTableCellEditor editor = new StringTableCellEditor(null);
                        editor.addDocumentListener(new DocumentAdapter() {
                            @Override
                            public void documentChanged(DocumentEvent documentEvent) {
                                if (table.getRowCount() == table.getEditingRow() + 1) {
                                    itemInfo.checkable = true;
                                    itemInfo.checked = true;
                                    table.getListTableModel().addRow(new ItemInfo());
                                }
                            }
                        });

                        return editor;
                    }
                    /*@Nullable
                    @Override
                    public TableCellRenderer getRenderer(ItemInfo item) {
                        return new DefaultTableCellRenderer(){
                            @Override
                            public Border getBorder() {
                                return new LineBorder(new Color(127, 127, 127));
                            }

                        };
                    }*/


                },
                new ColumnInfo<ItemInfo, String>("Value") {
                   /* @Override
                    public int getWidth(JTable table) {
                        return 282;
                    }*/

                    @Nullable
                    @Override
                    public String valueOf(ItemInfo itemInfo) {
                        return itemInfo.value;
                    }

                    @Override
                    public boolean isCellEditable(ItemInfo itemInfo) {
                        return itemInfo.isValueEditable();
                    }

                    @Override
                    public void setValue(ItemInfo itemInfo, String value) {
                        itemInfo.value = value;
                    }

                    @Nullable
                    @Override
                    public TableCellEditor getEditor(ItemInfo itemInfo) {
                        StringTableCellEditor editor = new StringTableCellEditor(null);
                        editor.addDocumentListener(new DocumentListener() {
                            @Override
                            public void beforeDocumentChange(DocumentEvent documentEvent) {
                            }

                            @Override
                            public void documentChanged(DocumentEvent documentEvent) {
                                if (table.getRowCount() == table.getEditingRow() + 1) {
                                    itemInfo.checkable = true;
                                    itemInfo.checked = true;
                                    table.getListTableModel().addRow(new ItemInfo());
                                }
                            }
                        });
                        return editor;
                    }
                   /* @Nullable
                    @Override
                    public TableCellRenderer getRenderer(ItemInfo item) {
                        return new DefaultTableCellRenderer(){
                            @Override
                            public Border getBorder() {
                                return new LineBorder(new Color(127, 127, 127));
                            }

                        };
                    }*/
                },
                new ColumnInfo<ItemInfo, String>(" ") {

                    int width = 20;

                    @Override
                    public int getWidth(JTable table) {
                        return width;
                    }

                    @Override
                    public Class getColumnClass() {
                        return String.class;
                    }

                    @Override
                    public String valueOf(ItemInfo o) {
                        return "_$$delete$$_";
                    }

                    @Nullable
                    @Override
                    public TableCellEditor getEditor(ItemInfo itemInfo) {
                        return new VoidRowCellEditer();
                    }

                    @Nullable
                    @Override
                    public TableCellRenderer getRenderer(ItemInfo itemInfo) {
                        return new DefaultTableCellRenderer() {
                            @Override
                            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
                                JButton button = new JButton("", AllIcons.Actions.Cancel);
                                button.setVisible(true);
                                button.setPreferredSize(new Dimension(width - 1, -1));
                                button.setBorder(table.getBorder());
                                button.setBackground(table.getBackground());
                                return button;
                            }
                        };
                    }
                },
        };
        return columnInfos;
    }


    public static class ItemInfo {

        private boolean checked;
        private boolean checkable;

        private String key;
        private boolean keyEditable;

        private String value;
        private boolean valueEditable;

        public ItemInfo() {
            this(false, false, true, "", true, "");
        }

        public ItemInfo(String key, String value) {
            this(true, true, true, key, true, value);
        }

        public ItemInfo(boolean checkable, boolean checked, boolean keyEditable, String key, boolean valueEditable, String value) {
            this.checkable = checkable;
            this.checked = checked;
            this.keyEditable = keyEditable;
            this.key = key;
            this.valueEditable = valueEditable;
            this.value = value;
        }

        public boolean isCheckable() {
            return checkable;
        }

        public void setCheckable(boolean checkable) {
            this.checkable = checkable;
        }

        public boolean isChecked() {
            return checked;
        }

        public void setChecked(boolean checked) {
            this.checked = checked;
        }

        public String getKey() {
            return key;
        }

        public void setKey(String key) {
            this.key = key;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }

        public boolean isKeyEditable() {
            return keyEditable;
        }

        public void setKeyEditable(boolean keyEditable) {
            this.keyEditable = keyEditable;
        }

        public boolean isValueEditable() {
            return valueEditable;
        }

        public void setValueEditable(boolean valueEditable) {
            this.valueEditable = valueEditable;
        }
    }
}
